//NEED TO REMEMBER THAT ON MATRIX INDEX 1
//NEED TO CHANGE CODE TO MOVE DOWNWARDS AND NOT SIDEWARDS


import java.util.*;
public class Solution {
    
    static int matrixNumber=0;
    static List<List<Integer>> matrix = new ArrayList<>();
    static List<List <Integer>> nextMatrix;
    
    
    
    public static void main (String [] args)
    {
        List <List<List<Integer>>> testMatrix = new ArrayList<>(); 
        //TEST CASES
        //We have to ensure that the test case is a 3d array as oppose to a 2d array to contain all the matrixes
        
        //As per challenge  - Test Case 1
       //Integer [][][]test = new Integer[][][] {   {{1,2,3},{4,5,6}},  {{7,8},{9,10},{11,12}},  { {13,14}, {15,16} } }; 
       
       //As per challenge  - Test Case 2
       //Integer [][][]test = new Integer[][][] {   {{1,2,3,4}},{{5},{6},{7},{8}}};
       
       
       //As per challenge  - Test Case 3/4  (both same)
       //Integer [][][]test = new Integer[][][] {   {{1, 2}, {3, 4}}, {{5, 6}, {7, 8}}, {{9, 10}, {11, 12}}  };
       
       
      //TEST CASES EXPLORING JAGGED ARRAYS (variants of TEST CASE 28 IN Document)
       //Integer [][][]test = new Integer[][][] {   {{1,2,3},{4,5,6}},  {{7,8},{10},{11,12}},  { {13,14}, {15,16} } }; 
       
       
      //TEST CASES EXPLORING JAGGED ARRAYS (variants of TEST CASE 28 IN Document) 
      //This relies on the matrixMultiplication initialisation
       //Integer [][][]test = new Integer[][][] {   {{1,2,3},{4,5,6}},  {{7,8},{10,11},{11,12}},  { {13,14,17}, {15,16} } }; 
       
       
       //TEST CASES EXPLORING JAGGED ARRAYS (variants of TEST CASE 28 IN Document) 
       //Integer [][][]test = new Integer[][][] {   {{1,2,3},{4,5}},  {{7,8},{10,11},{11,12}},  { {13,14,17}, {15,16} } }; 
        
        //TEST CASES EXPLORING JAGGED ARRAYS (variants of TEST CASE 28 IN Document) 
       //Integer [][][]test = new Integer[][][] {   {{1,2},{4,5,6}},  {{7,8},{10,11},{11,12}},  { {13,14,17}, {15,16,17} } }; 
        
        
       //TEST CASES EXPLORING JAGGED ARRAYS (variants of TEST CASE 28 IN Document)
       //This will get picked up on area of code I had written towards bottom part of code
       //Integer [][][]test = new Integer[][][] {   {{},{4,5,6}},  {{7,8,6},{10,14},{11,12}},  { {13}, {15,16} } }; 
    
    
    
    
    //HERE!!!!!!!!!!!!!!!!!!!!!!!!
        //Integer [][][]test = new Integer[][][] {   {{1,2},{3,4},{5,6}},  {{7,8},{10,14},{0}},  { {13}, {15,16} } }; 
        
        
        //With this test case it has not performed jump to new column (FAIL)
        //used workaround to examine RowInfo
        Integer [][][]test = new Integer[][][] {   {{1,2,3},{4,5,6}},  {{7,8},{9,10},{11,12}},  { {13,14}, {16} } }; 
        
       
       //TEST CASES EXPLORING JAGGED ARRAYS (variants of TEST CASE 28 IN Document) 
        //Integer [][][]test = new Integer[][][] {   {{1,2,3},{4,5,6}},  {{7,8},{9,2},{11,12}},  { {13,14}, {16,87},{3,4} } }; 
    
    
        
       //TEST CASES EXPLORING JAGGED ARRAYS (variants of TEST CASE 28 IN Document)
       //This just passes through my entire code without a single calculation, so applied fix as it passes through nextmatrix check
       //Integer [][][]test = new Integer[][][] {   {{1,2,3},{4,5,6}},  {{},{10,14},{11,12}},  { {13}, {15,16} } }; 
       
       
        //TEST CASES EXPLORING JAGGED ARRAYS (variants of TEST CASE 28 IN Document)
       //This performs a calculation and no errors
       //Integer [][][]test = new Integer[][][] {   {{1,2,3},{4,5,6}},  {{1,7},{25,14},{}},  { {13,15}, {15,16} } }; 
       
       //TEST CASES EXPLORING JAGGED ARRAYS (variants of TEST CASE 28 IN Document)
       //This will be handled validation in later part of code
       //Integer [][][]test = new Integer[][][] {   {{1,2,3},{}},  {{1,7},{25,14},{4,8}},  { {13,15}, {15,16} } }; 
       
       
       //-------------AMIT-------------------
       //TEST CASES EXPLORING JAGGED ARRAYS (variants of TEST CASE 28 IN Document)
       //This performs a calculation....
       //Integer [][][]test = new Integer[][][] {   {{1,2,3},{4,5,6}},  {{1,7},{25,14},{4,8}},  { {}, {15,16} } }; 
       
        
        //TEST CASES EXPLORING JAGGED ARRAYS (variants of TEST CASE 28 IN Document)
       //This performs a calculation....
       //Integer [][][]test = new Integer[][][] {   {{1,2,3},{4,5,6}},  {{1,7},{25,14},{4,8}},  { {34,45}, {} } }; 
       //Integer [][][]test = new Integer[][][] {   {{1,2,3},{4,5,6}},  {{1,7},{25,14},{4,8}},  { {34,45}, {} } }; 
        

       //TEST CASES EXPLORING JAGGED ARRAYS (TEST CASE 28 IN Document exactly)
       //Integer [][][]test = new Integer[][][] {   {{1,2,3},{4,5,6}},  {{7,8,6},{10,14},{11,12}},  { {13,14}, {15,16} } }; 
       
       
       //TEST CASES EXPLORING JAGGED ARRAYS (TEST CASE 28 IN Document exactly)
       //But it is error free, so informed end user excess numbers
       //Integer [][][]test = new Integer[][][] {   {{1,2,3},{4,5,6}},  {{7,8},{9,10,14},{11,12}},  { {13,14}, {15,16} } }; 
       
       //TEST CASES EXPLORING JAGGED ARRAYS (TEST CASE 28 IN Document exactly)
       //Integer [][][]test = new Integer[][][] {   {{1,2,3},{4,5,6}},  {{7,8,6},{10,14},{11,12}},  { {13,14}, {15,16} } }; 
       
       //TEST CASES EXPLORING JAGGED ARRAYS (TEST CASE 28 IN Document exactly)
       //Integer [][][]test = new Integer[][][] {   {{1,2,3},{4,5,6}},  {{7,8},{10,14},{11,12}},  { {13}, {15,16} } }; 
       
        
       
       //
       
       
       //ADDITIONAL TEST CASES
       
       //Integer [][][]test = new Integer[][][] {   {{1,2,3},{4,5,6}},  {{7,8},{9,10},{11,12}},  { {13,14}, {15,16} },    { {17,18}, {19,20} },{ {17,18}, {19,20} }}; 
        
       //Integer [][][]test = new Integer[][][] {   {{1,2,3},{4,5,6}},  {{7,8},{9,10},{11,12}},  { {13,14}, {15,16}},  { {17,18}, {19,20},{17,18}, {19,20}}, { {21,22,23,24}, {25,26,27,28},{29,30,31,32}} };
                                                                                            //AB=2 x 2
        
        //revisit
        //Integer [][][]test = new Integer[][][] {   {{1,2,3},{4,5,6},{7,8,9}},  {{10,11,12},{13,14,15},{16,17,18}},  { {19,20,21}, {22,23,24}} };

        
        
        for (Integer [][] item: test)
        {
            //THIS WAS CRITICAL PIECE OF CODE HERE...
            //OTHERWISE THERE WOULD BE THE SAME OBJECT REFERENCE EACH TIME!
            matrix = new ArrayList<>();
            
            //At this point we have the entire contents that would represent the List<List<Integer> single matrix
            //since we know that {1,2,3} would be a List<Integer> and {4,5,6} would be a list <Integer>
        
            for (Integer [] row: item)
            {
                matrix.add(Arrays.asList(row));    //similar to transposing matrix challenge
            }
            testMatrix.add(matrix);
        }
        
        matrixNumber=0;
        //method call
        matrixMultiplication(testMatrix);
    }
    
    
    public static List<List<Integer>> matrixMultiplication(List<List<List<Integer>>> matrices) 
    {
        String rowMatrix;
        String currentEntry=null;
        String prevEntry=null;
        
        StringJoiner excessRowReport = new StringJoiner("   ,");
        
        StringJoiner [][] matrixMultiplicationCalculations;
        
        int numWritesToLastIndexMultiplicationMatrix;
        
        boolean hasReachedEndRow=false;
        
        boolean hasStartedMultiplication=false;
        
        List<List<Integer>> finalMatrix = new ArrayList<List<Integer>>();
        
        Integer multiplication;
        
        int rowCounterFirstMatrix=0;
        
        List<Integer> temp = new ArrayList<Integer>();
        int rowsNextMatrix=0;
        int size=0;
        int matricesSize=matrices.size();
        int numElementsInList=0;
        int counter=0;
        int i;
        int currentInteger;
        
        //StringJoiner rowColMultiplication = new StringJoiner("+");
        
        boolean hasStartMatrix=true;
        boolean hasPerformedValidation=false;
        int numElementsInRow=0;
        boolean hasProcessed=false;
        
        int posPrevMatrixRowLevel=0;
             
        int numMatrixes=0;

        //I am using this size based on principle that
        //number columns Matrix A needs to be equal 
        //number rows Matrix B
        //This is easiest way to ascertain a suitable dimension
        //of Matrix B
        //really this would need to be in a try and catch statement should there only be one matrix!

	//we know the first row dimension, this must match the number columns Matrix B
    //So both take same dimensions

    //lets say if there is also matrix C
    //we would apply the principle again both dimensions are taken from matrix C column size.
    //Hence it is best not to declare size at moment

    Integer [][]matrixMultiplication = null;
    
    List <List<Integer>> matrixMultiplicationList = new ArrayList<>();

        
        //The following structure will ensure that
        //each each matrix can be obtained from the matrices
        //We have to remember that inner Lists can still be accessed via their index locations. This can be obtained via .get
        //We know that similar to other transposing matrix challenge, we can obtain the size (matrices) which will output the number of elements..
        //We know in this case this deals with List<List<Integer>>
        //We can now formulate a do while loop which would process the List<List<Integer>> within matrices until it reaches the size of matrices.

        //This will present all matrix in true form in order to visualise and assist with coding 
        System.out.println("***ALL MATRIX*******");
        do
        {
            matrix=matrices.get(numMatrixes);
            
            System.out.println("\nMatrix" +"("+numMatrixes+"):");

            for (List<Integer> row: matrix)
            {
                System.out.println(row);
            }
            numMatrixes++;
            System.out.println("\n");
            }while(numMatrixes<matrices.size());

            numMatrixes=0;

       //This do while loop is main code and can execute up to (matrices.size()-1)
       do
        {
            hasProcessed=false;
            matrix=matrices.get(counter);
            
            //we need to display the multiplied matrix and give indication of which matrixes were multiplied
            
            
            //AMIT
            
            System.out.println("BACK!!!!!!!!!!!!!!!!");
            
            if (counter>0 && hasStartedMultiplication)
            {
                System.out.println("\n\n66666666666666666666666666666666666666666666Matrix multiplication: " + "Matrix ("+(counter-2)+") x Matrix ("+(counter-1)+")");
                
                for (Integer []m: matrixMultiplication)
                {
                System.out.println(Arrays.toString(m));
                //inline with Test case 21, I need to store rows of matrixMultiplication into List<List<Integer>
                //I need to change the data type of matrixMultiplcation to Integer to fulfill this
                
                
                
                
                matrixMultiplicationList.add(Arrays.asList(m));
                
                }
                
            //the best option is to place the multipliedmatrixList into the next position on the matrices...
                //However due to object referencing , I need to ensure that a new instance is created of  multipliedMatrixList
                //otherwise it will be pointing to same object reference
                //The only time we do not want to perform this operation if there are two matrixes in the matrice.
                //since we would have already completed the multipliedMatrix
                
                if (matrices.size()!=2)
                {
                    System.out.println("ADDED Multiplication Matrix into the chain at index: " + (counter));
                    matrices.add(counter,matrixMultiplicationList);
                    hasStartedMultiplication=false;
                    
                    System.out.println("It will perform multiplication with Matrix("+(counter+1)+")");
                    
                    for (List<Integer> w: matrices.get((counter+1)))
                {
                    
                System.out.println(String.valueOf(w));
                    
                }
                    
                    
                    
                    
                    //this is required as part of test case 27
                    matricesSize=matrices.size();
                    
                    //we now need to
                    matrix=matrices.get(counter);
                }
            }
            System.out.println("\n\n------Matrix" +"("+counter+"):");
            
            //We need to clear this content
            matrixMultiplicationList = new ArrayList<>();
            
            //we would perform this to obtain the next matrix
            //I had to scrap this since for some reason, it was giving information for incorrect matrix.
            //I do not think issue was related to object referencing..
            //But I am going to stay away for now
            nextMatrix=matrices.get(counter+1);
            
            
        
        //for data such as below, it would process the execution of first row in matrix 0 against both columns in
        //Matrix B since it has only iterated the for each loop once....
        //Really we need it to perform the iteration the same number of times as the number rows in matrix 0
        //this can be obtained via matrix.size();
        //Matrix(0):
        //[1, 2, 3]
        //[4, 5, 6]

        //Matrix(1):
        //[7, 8]
        //[9, 10]
        //[11, 12]
        
        //for (int t=0; t<matrix.size(); t++)
        //{
        
        
        
        
        
            
            System.out.println("^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^");
            //At this point, we know the netMatrix and also matrix... Both of these are required for test case 29
            //we know the the StringBuilder and storing into the
            
             //at this point as per test case 29, we can also create array of StringBuilder so that we have running information of the
            //operations undertaken at each index
            
            matrixMultiplicationCalculations=new StringJoiner[nextMatrix.get(0).size()][matrix.size()];
            
            //Similar to matrixMultiplication, we need to instantiate each object reference to "+"
            
            //for each row.... we need to traverse through each column and perform instantiation
            //This time, we can not rely on the properties of matrixMultiplication since it has not dimensions yet
            
            System.out.println("Size of rows: " + nextMatrix.get(0).size());
            System.out.println("Size of cols: " + matrix.size());
            
            //However it gets more confusing, We know that in each index of the matrixMultiplication, there are several calculations
            //So we need the StringBuilder to be applicable at these points...
            //Otherwise it would not create "+" between the additions...
            //And this is the whole point
            
            System.out.println("********************************************************************************************************");
            
            for (int q=0; q<nextMatrix.get(0).size(); q++)
            {
                for (int r=0; r<matrix.size(); r++)
                {
                    System.out.println("setting for: " + q + "," + r);
                    matrixMultiplicationCalculations[q][r] = new StringJoiner("+");
                }
            }
        
        
        for (List<Integer> ee: matrix)
        {
            rowMatrix = String.valueOf(ee);
            System.out.println("THIS IS ROW COUNTER MATRIX("+counter+"): " + rowCounterFirstMatrix);
            System.out.println("------------------------------------------THIS IS ROW DATA MATRIX("+counter+"): " + ee);
            //I can no longer use this notation since it will not be compatible with rest of my code
            hasProcessed=false;
            numWritesToLastIndexMultiplicationMatrix=0;
            hasReachedEndRow=false;
                
            for (int k=0; k<ee.size(); k++)
            {
                
                //System.out.println("EXECUTE1");
               
                currentInteger = ee.get(k);
                //I am now choosing to look ahead at the next matrix as soon as a number appears on the screen.
                //The only exception of course is the final matrix since it would have been processed by penultimate matrix.
                
                System.out.println("counter: " + counter);
                System.out.println(matricesSize-1);
                
                if(counter!=matricesSize-1)
                {
                System.out.println("INSIDE");
                //System.out.println("EXECUTE2");
                
                //In this matrix we know that numbers are retrieved left to right.
                //I am going to attempt completing the multiplication in a similar manner to a human.
                /*
                [1, 2, 3] 
                [4, 5, 6]

                [7,    8] 
                [9,   10]
                [11, 12]
                */
          
            
            //we would perform this to obtain the next matrix
            //matrix=matrices.get(counter+1);
            
            
            
            
            
            

            System.out.println("BOOL hasProcessed: " + hasProcessed + "  " + nextMatrix.get(0).size());
            
            
            
            //This is for test case 2 presented in the challenge.
            //Issue arose due to single dimension matrix 2.
            //It did not enter the main code again unless this was implemented.
            
            //checks if there is one element in the first row of nextMatrix
            //We are using 0 because this was the information provided to configure matrixMultiplication
            //so it is enforcing logic without creating exception
            //Also we have no indexing configured yet for nextMatrix
            
            if (nextMatrix.get(0).size()==1)
            {
                //we set boolean false so that it can enter main area of code 
                hasProcessed=false;
            }
            
            
            if (!hasProcessed)
            {
               
            //System.out.println("EXECUTE3");
            //But I also have this option to perform a similar operation as above but at a more granular level

            //we have created an outer if loop because it will otherwise execute multiple times. We are only seeking one occurrence for next matrix
            
            int rowCounterNextMatrix=0;
            
            //System.out.println("number rows in next matrix "+ "("+(counter+1)+"): -  " + nextMatrix.size());
            System.out.println("number cols in next matrix "+ "("+(counter+1)+"): -  " + nextMatrix.get(0).size());  
            
            System.out.println("number rows in matrix "+ "("+(counter)+"): -  " + matrix.size());
            //System.out.println("number cols in matrix "+ "("+(counter)+"): -  " + matrix.get(counter).size()); 
            
            
            //I can configure the required size of the matrix now
            //We need to use number rows in Matrix A  to identify the numbe of columns in matrixMultiplication
            //We need to use the number columns in Matrix B to identify number rows in matrixMultiplication
            //This should only happen once until it reaches the next matrix
            
            if (!hasStartedMultiplication)
            {  //System.out.println("EXECUTE4");
                System.out.println("****************************CONFIGURING BLANK MULTIPLICATION MATRIX*******************************************");
            matrixMultiplication = new Integer[nextMatrix.get(0).size()][matrix.size()];
            
           
            
            
            
            
            //This required chatGPT intervention... I was continuously getting NullPointerException when attemptng to perform
            //matrixMultiplication[rowCounterFirstMatrix][z] = matrixMultiplication[rowCounterFirstMatrix][z]  + multiplication;
            //It only occurred when I extended the
            //******************FROM ChatGPT
            
            System.out.println(matrix.size());
            System.out.println(nextMatrix.get(0).size());
            
            //this is in relation to test case 28
            try
            {
            
            for (int a = 0; a < matrix.size(); a++) {
                System.out.println("a: " + a);
    for (int b = 0; b < nextMatrix.get(0).size(); b++) {
        System.out.println("b: " + b);
        matrixMultiplication[a][b] = 0;
    }
}
}
catch (ArrayIndexOutOfBoundsException e)
{
    System.out.println("1The current dimension of matrixMultiplication: " + "["+nextMatrix.get(0).size()+"]"+"["+matrix.size()+"]");
    //System.out.println("Because the size of " + nextMatrix.get(0).size() + )
    //matrixMultiplication = new Integer[nextMatrix.get(0).size()][matrix.size()];
            
    
    //Because the value in nextMatrix.get(0).size() = 3, it will cause the exception
}

//***********************************************************************************************

            
            
            
            
            
            hasStartedMultiplication=true;
            }

            System.out.println("Matrix (W=" + matrix.size()+")  x  (H=" + nextMatrix.get(0).size()+")" + " configured to store Matrix " + counter + " x  Matrix " + (counter+1));
            
            
             //OPTION 2 - index based
             
             List<Integer> rowInfo = new ArrayList<>();
             int pos=0;
             
             
             //since the first row is the master to enter the for loop, we need to consider if the
             //first row is actually blank, this can be achieved via:
             //Integer [][][]test = new Integer[][][] {   {{1,2,3},{4,5,6}},  {{1,7},{25,14},{4,8}},  { {}, {15,16} } }; 
             
             
             if (nextMatrix.get(0).size()==0)
             {
                 System.out.println("8The current dimension of matrixMultiplication: " + "["+nextMatrix.get(0).size()+"]"+"["+matrix.size()+"]");
                System.out.println("It EXPECTS: " + matrix.size() + " elements per row");
                System.out.println("matrix" + "("+(counter+1)+")" + " row:" + rowCounterNextMatrix +  " " + nextMatrix.get(0) + " size: " + nextMatrix.get(0).size() + " invalidates this");
                System.exit(0);
                 
             }
             
             
             //this will go through each column
                    for (int z=0; z<nextMatrix.get(0).size(); z++)
                    {
                        System.out.println("*****************Column number: " + z);
                        //for each column we stil need to get the entire row
                        
                         posPrevMatrixRowLevel=0;
                        
                        
                    int resetStart=0;
                    //int y;
                    
                    
                        
                        
                    
                        
                    for (int y=0; y<nextMatrix.size();y++)
                    {
                       //System.out.println("EXECUTE6");
                        if (y<nextMatrix.get(0).size())
                    {
                        //System.out.println("EXECUTE7");
                       
            //this is getting the rows from the nextmatrix 
            for (int m=0; m<nextMatrix.size(); m++)
            {   
                //System.out.println("EXECUTE8");
               
                //for each row we need to get the size so that all integers can be collated from the row
                for (int j=0;j<nextMatrix.get(m).size();j++)
                {
                    
                    //used for test case 28
                    //we know we are interested in number of rows
                    //hence we need to check if content in row otherwise it will give blank calculations at the end
                    
                    System.out.println("------------------------------------------------------------------------------");
                    System.out.println(nextMatrix.get(m));
                    
                    if (nextMatrix.get(m).size()==0)
                    {
                        System.out.println("NO CONTENT");
                        System.exit(0);
                    }
                    
                    //System.out.println("EXECUTE9");
                    
                    //int [] row  = new int[]Arrays.asList(nextMatrix.get(m));
                    //int [] row = {1,2,3};
                    
                    
                    if (m==0)
                    {
                        rowCounterNextMatrix=0;
                    }
                    
                    
                    System.out.println("****************%^&%$^%$^%$^$^%$^$^$^");
                    
                    System.out.println("size of row: " + nextMatrix.get(0).size());
                    System.out.println("row number next matrix: " + y);
                    System.out.println("size of row next matrix -1 : " + (rowInfo.size()-1));
                    System.out.println("ROWINFO: " + rowInfo);
                    System.out.println("****************%^&%$^%$^%$^$^%$^$^$^");
                    
                    if (rowInfo.size()==0)
                    {
                        System.out.println(rowCounterNextMatrix);
                        System.out.println("2The current dimension of matrixMultiplication: " + "["+nextMatrix.get(0).size()+"]"+"["+matrix.size()+"]");
                        System.out.println("It EXPECTS: " + matrix.size() + " elements per row");
                        nextMatrix=matrices.get(counter+2);
                        System.out.println("matrix" + "("+(counter+2)+")" + " row:" + (rowCounterNextMatrix+1) +  " " + nextMatrix.get(rowCounterNextMatrix+1) + " size: " + nextMatrix.get(rowCounterNextMatrix+1).size() + " invalidates this");
                        System.exit(0);
                        
                    }
                    
                    //y relates to y<nextMatrix.size()
                    //this refers to numbers rows in next Matrix
                    
                    //if number rows in next matrix (y) is equal to (row size-1) 
                    
                    
                    
                    //******Having the nextMatrix.get(0).size()!=1 was used to support this test case
                    //Integer [][][]test = new Integer[][][] {   {{1,2,3,4}},{{5},{6},{7},{8}}};
                    
                    
                    
                    if (y==(rowInfo.size()-1) && nextMatrix.get(0).size()!=1)
                    {
                        System.out.println("BREAKING");
                        posPrevMatrixRowLevel=0;
                        break;
                    }
                    
                    //I had to include this since for test cases such as
                    //Integer [][][]test = new Integer[][][] {   {{1,2,3},{4,5,6}},  {{7,8},{9,10},{11,12}},  { {13,14}, {16} } }; 
                    //it is not jumping column, so I have the wrong data on the screen to write clear reason for error
                    
                    
                    
                    
                    
                    else
                    {
                        System.out.println("retrieving row: " + rowCounterNextMatrix + " from matrix (" + (counter+1)+")");    
                    }
                    
                    
                        
                    rowInfo=new ArrayList<>(nextMatrix.get(m));
                    System.out.println("size of nextMatrix row: " + rowInfo.size());
                    
                    
                    
                    
                    
                    //we can use logic here to check if the value of z which denotes the column has increased from it previous attempting on that given row
                    //we know the repetition has occured when it has started the row again...
                    
                    
                    System.out.println("BOOLEAN STATUS: " + hasReachedEndRow);
                    
                    if (!hasReachedEndRow)
                    {
                    
                    System.out.println("-----------THIS IS ROW DATA: " + nextMatrix.get(m));
                    
                    //As per Test Case 28, I am placing logic here so that end user is aware if there is an element of jagged array
                    //we expect the row length (i.e number of columns) to be same as number rows of matrix
                    
                    
                    //matrixMultiplication = new Integer[nextMatrix.get(0).size()][matrix.size()];
                    
                    //We are now capturing all the row data in which it exceeds the expectations in the matrixMultiplication
                    //this is so that end user is exactly aware without any confusions.......
                    
                    int seekPosition=0;
                    StringJoiner excessRowItems = new StringJoiner(",");
                    
                    
                    if (rowInfo.size()!=matrixMultiplication[0].length)
                    {
                        currentEntry = "Row length:" + rowInfo.size()+" (matrix" + "("+(counter+1)+") row:" +rowCounterNextMatrix+ "   "+ nextMatrix.get(m)+") "  + " inconsistent with length expectations" + "("+matrixMultiplication[0].length+") in multiplcation matrix";
                        
                       if (!currentEntry.equals(prevEntry))
                       {
                        
                        System.out.println(currentEntry);
                        excessRowReport.add(currentEntry);
                        
                        
                        for (int x: nextMatrix.get(m))
                        {
                            seekPosition++;
                            
                            if (seekPosition>matrixMultiplication[0].length)
                            {
                                excessRowItems.add(String.valueOf(x));
                                
                            }
                        }
                        
                    }
                        
                    }
                    prevEntry = currentEntry;
                    
                    if (seekPosition!=0)
                    {
                    System.out.println("["+excessRowItems+"] are exempt from multiplcation matrix");
                    }
                    
                    
                    
                    
                    
                    rowCounterNextMatrix++;
                    
                    //but we know that we are only interested in the first item from each row
                    //since we are processing the column
                    
                    //AT THIS MOMENT, WE HAVE TWO FOR LOOPS WHICH IS GOING THROUGH ROWS
                    //IN NEXT MATRIX AND ALSO CREATED THE ROW IN A LIST
                    
                    //------
                        
                        //once we go through the rows, we need to get the actual row
                    
                    
                    //for (int p=0; p<rowInfo.size(); p++)
                    //{
                    System.out.println("Row number matrix("+(counter+1)+"):\t" + y);
                    
                    
                        try
                        {
                        System.out.println("element: " + rowInfo.get(z));
                        }
                        catch (IndexOutOfBoundsException e)
                        {
                           
                        System.out.println("2The current dimension of matrixMultiplication: " + "["+nextMatrix.get(0).size()+"]"+"["+matrix.size()+"]");
                                System.out.println("It EXPECTS: " + matrix.size() + " elements per row");
                                System.out.println("matrix" + "("+(counter+1)+")" + " row:" + rowCounterNextMatrix +  " " + nextMatrix.get(m) + " size: " + nextMatrix.get(m).size() + " invalidates this");
                                System.exit(0);
                        }
                        
                        
                        //in here need to go through the row in previous matrix
                        //this is the row level
                        
                        
                        //we know there is a relationship between ith element in Matrix A and jth element in matrix B.
                        //using the for loop will perform operation for size of elements in that given row
                        //we can just scrap the for loop
                         //for (int g=0; g<ee.size(); g++)
                        //{
                            //System.out.println("info in row: " + ee);
                            System.out.println(ee);
                            System.out.println("posPrevMatrixRowLevel: "+ posPrevMatrixRowLevel);
                            System.out.println("rowCounterNextMatrix: " + rowCounterNextMatrix);
                            System.out.println("rows in matrix: " + matrix.size());
                            System.out.println("ee: " + ee);
                            System.out.println("rowinfo size: " + rowInfo.size());
                            
                            
                //Integer [][][]test = new Integer[][][] {   {{1,2,3},{4,5,6}},  {{7,8},{9,10},{11,12}},  { {13,14}, {16} } }; 
                            
                            
                    //System.out.println("2The current dimension of matrixMultiplication: " + "["+matrixMultiplication.length+"],"+"["+matrixMultiplication[0].length+"]");
                    //System.out.println("Accessing row index: " + rowCounterNextMatrix + " from " + nextMatrix.get(m) + " invalidates this");            
                             //Integer [][][]test = new Integer[][][] {   {{1,2,3},{4,5,6}},  {{7,8},{10,14},{0}},  { {13}, {15,16} } }; 
                             
                             
                            try
                            {
                            System.out.println("INFO prev: " +ee.get(posPrevMatrixRowLevel));
                            }
                            catch (ArrayIndexOutOfBoundsException e)
                            {
                                System.out.println("3The current dimension of matrixMultiplication: " + "["+matrixMultiplication.length+"]"+"["+matrixMultiplication[0].length+"]");
                                //System.out.println("It faciliates: " + matrix.size() + " elements per row");
                                //System.out.println("It faciliates: " + matrix.size() + " elements per row");
                                
                                //matrixMultiplication = new Integer[nextMatrix.get(0).size()][matrix.size()];
                                
                                //number rows in nextMatrix is columns in matrixMultiplication
                            //number cols in matrix is rows in matrixMultiplication
                                
                                
                                
                                
                                //if the number of columns is greater than rows in next matrix
                                if(ee.size()>matrixMultiplication.length)
                                {
                                    System.out.println("It EXPECTS: " + matrix.size() + " elements per row");
                                    System.out.println("matrix" + "("+(counter)+")" + " row:" + rowCounterFirstMatrix +  " " + matrix.get(rowCounterFirstMatrix) + " size: " + matrix.get(rowCounterFirstMatrix).size() + " invalidates this");
                                }
                                
                                
                                //this would happen for similar case
                                //Integer [][][]test = new Integer[][][] {   {{1,2,3},{4,5,6}},  {{7,8},{9,10},{11,12}},  { {13,14}, {16} } }; 
                                //its as an offset of a multiplication matrix added
                                
                                
                                //----------------------------
                                //if the number of columns is greater than rows in next matrix
                                if(ee.size()>matrixMultiplication.length)
                                {
                                    System.out.println("It EXPECTS: " + matrix.size() + " elements per row");
                                    System.out.println("matrix" + "("+(counter)+")" + " row:" + rowCounterFirstMatrix +  " " + matrix.get(rowCounterFirstMatrix) + " size: " + matrix.get(rowCounterFirstMatrix).size() + " invalidates this");
                                }
                                
                                
                                
                                if(nextMatrix.get(m).size()>matrixMultiplication[0].length)
                                {
                                    System.out.println("It EXPECTS: " + matrix.size() + " elements per row");
                                    System.out.println("matrix" + "("+(counter+1)+")" + " row:" + rowCounterNextMatrix +  " " + nextMatrix.get(m) + " size: " + nextMatrix.get(m).size() + " invalidates this");
                                }
                                
                                if (rowInfo.size()>matrixMultiplication.length)
                                {
                                    System.out.println("1Accessing matrix(" + counter+") row index: " + rowCounterNextMatrix + " from " + nextMatrix.get(m) + " invalidates this");
                                }
                                
                                //if the number of columns in matrix is less than rows in next matrix
                                
                                if (ee.size()<rowCounterNextMatrix)
                                {
                                    System.out.println("2Accessing matrix(" + counter+") row index: " + rowCounterNextMatrix + " from " + ee + " invalidates this");
                                    
                                }
                                
                                                        System.exit(0);
                            }
                            
                            
                            multiplication =  ee.get(posPrevMatrixRowLevel) *rowInfo.get(z);
                            
                            System.out.println(ee.get(posPrevMatrixRowLevel) + " X " + rowInfo.get(z));
                            
                            
                            System.out.println(multiplication);
                            
                            //we know we have these dimensions.
                            //for each column in nextMatrix we expect to fill out entries across entire row
                            //in matrixMultiplication
                            
                            //we know that whilst it processes row 0 on matrix 0 (rowCounterFirstMatrix)  and oolumn 0 on Matrix B (z)
                            //it would store the value in  matrixMultiplication[0][0]
                            
                            //we know that whilst it processes row 0 on matrix 0 (rowCounterFirstMatrix)   and oolumn 1 on Matrix B (z)
                            //it would store the value in  matrixMultiplication[0][1]
                            
                            //we also know that we do not want to overwrite value at those index.. we want to add existing content back into it
                            
                            /*
                            Matrix A             Matrix B                            
                            1,2,3                7, 8
                            4,5,6                9, 10
                                                 11,12
                              
                              
                              
                              
                             */
                             
                             System.out.println(rowCounterFirstMatrix);
                             System.out.println(z);
                             
                             
                             //This is still part of Test case 28
                             
                             
                             try
                             {
                             matrixMultiplication[rowCounterFirstMatrix][z] = matrixMultiplication[rowCounterFirstMatrix][z]  + multiplication;
                             }
                             catch (ArrayIndexOutOfBoundsException e)
                             {
                              System.out.println("4The current dimension of matrixMultiplication: " + "["+nextMatrix.get(0).size()+"]"+"["+matrix.size()+"]");
                              System.out.println("It EXPECTS: " + matrix.size() + " elements per row");
                              System.out.println("matrix" + "("+(counter+1)+")" + " row:" + rowCounterNextMatrix +  " " + nextMatrix.get(m) + " size: " + nextMatrix.get(m).size() + " invalidates this");
                              System.exit(0);
                             }
                             
                             
                             System.out.println("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!Value in multiplication matrix: " + matrixMultiplication[rowCounterFirstMatrix][z] + "\t" + "["+rowCounterFirstMatrix+"],["+z+"]" );
                            
                            System.out.println(rowCounterFirstMatrix);
                            System.out.println(z);
                            
                            
                            matrixMultiplicationCalculations[rowCounterFirstMatrix][z].add("(" + ee.get(posPrevMatrixRowLevel) + "x" +rowInfo.get(z) +"="+String.valueOf(multiplication)+")");
                            System.out.println(matrixMultiplicationCalculations[rowCounterFirstMatrix][z]);
                            
                            //ee.get(posPrevMatrixRowLevel) + " X " + rowInfo.get(z)
                            
                            
                            //This is for test case 26
                            //we would create the backupLocationZ since we know that it has reached the last index.
                            //We know however that it reaches the last index of the row more than once depending on the dimension..
                            //Number times it reaches the last index of the matrixMultiplication for a given row is determined by
                            //the number of rows in next Matrix...
                            //So ultimately we only want to set hasReachedEndRow=true when it is has written to the last index this many times
                            
                            //if it intends to write to the last column on the multiplication matrix
                            if (z==(matrixMultiplication.length-1))
                            {
                                
                                //it counts the number of writes
                                numWritesToLastIndexMultiplicationMatrix++;
                                
                                //as described above, number times it writes to any index in the multiplication matrix
                                //is dependent on the number rows in next matrix
                                //so if it has performed this many writes to last index on the row
                                //it will set the boolean. This boolean will wrap around massive section of code
                                if (numWritesToLastIndexMultiplicationMatrix==nextMatrix.size())
                                {
                                
                                 hasReachedEndRow=true;
                             }
                        }
                            
                            
                            
                            
                            
                            //This is for test case 26
                            //At this point we would create the backupLocationZ since we know that it has reached the last index
                            //We know however that it reaches the last index of the row more than once depending on the dimension..
                            //Number times it reaches the last index of the matrixMultiplication for a given row is determined by
                            //the number of rows in next Matrix...
                            //So ultimately we only want to set hasReachedEndRow=true when it is completely finished.
                            
                            //So we need to keep a count of where it per
                            
                                
                             
                             
                            //matrixMultiplication = new int[nextMatrix.get(0).size()][matrix.size()];
                            
                            
                            
                            
                            
                           
                        //}
                        posPrevMatrixRowLevel++;
                        
                        
                        
                        //System.out.println("vak k: " + ee.get(k+pos));
                        
                        pos++;
                        break;
                    //}
                }
                else
                {
                    System.out.println("---------------------------------------------------");
                    System.out.println("previous written to each index location of multiplication matrix: " + nextMatrix.size() + "  MAXIMUM times");
                    System.out.println("---------------------------------------------------");
                    
                }
                    }
                    //rowCounter=0;
                }
                    pos=0;
                }     
                    }
            }

            hasProcessed=true;
            
            }
            System.out.println("LEAVE HERE");
        }
        System.out.println("LEAVE HERE1");
                
                if (matrixNumber<counter && hasStartMatrix)
                {
                    System.out.println("This is first integer in next matrix: " + k);
                    hasStartMatrix=false;  
                    hasProcessed=false; 
                }

                numElementsInList++;
                numElementsInRow++;
            }
            

            //Using this technique will also ensure that I can check if the matrix is valid dimension and terminate the application
            //WE KNOW THAT NUMBER columns in Matrix A should match rows Matrix B
	    //NOTE for simplicity, I have assumed columms in Matrix A are uniform across its rows.
	    //We know if it had a jagged array, it would be a mismatch against the number rows in Matrix B	
           //Once I have finished the entire challenge, I can potentially extend my validation at this level
           //Since in this challenge there is every possibility of human error populating the matrix!
            
            String rowEntry=null;
            
            if(counter!=(matricesSize-1))
            {
                for (List<Integer> rows: matrices.get((counter+1)))
                {
                    rowsNextMatrix++;
                    rowEntry=String.valueOf(rows);
                }
                    System.out.println(numElementsInRow);
                    System.out.println(rowsNextMatrix);
                    //System.out.println(rowEntry);
                    //System.out.println(matrix.get(k));
                    
                    
                    //I have now used this area in Test case 28 validation to support any blank row entries in matrix
                    
                    if (numElementsInRow!=rowsNextMatrix)
                    {
                        System.out.println(rowEntry);
            System.out.println("columns " + "("+numElementsInRow+") in Matrix"  + "("+counter+")" + "(Row:" +rowCounterFirstMatrix + " content: " +  rowMatrix +  ") should match " +  rowsNextMatrix + " rows in matrix("+(counter+1)+")");
                        System.exit(0);
                    }
                    else
                    {
                        
                        System.out.println(rowsNextMatrix);
                        //System.out.println(nextMatrix.get(2));
                        
                        
                        //Integer [][][]test = new Integer[][][] {   {{1,2,3},{4,5,6}},  {{1,7},{25,14},{4,8}},  { {}, {15,16} } }; 
                        
                        /*
                        if (nextMatrix.get(rowsNextMatrix).size()==0)
                        {
                            System.out.println("7The current dimension of matrixMultiplication: " + "["+nextMatrix.get(0).size()+"]"+"["+matrix.size()+"]");
                                System.out.println("It EXPECTS: " + matrix.size() + " elements per row");
                                System.out.println("matrix" + "("+(counter+1)+")" + " row:" + rowsNextMatrix +  " " + nextMatrix.get(rowsNextMatrix) + " size: " + nextMatrix.get(rowsNextMatrix).size() + " invalidates this");
                                System.exit(0);
                        }
                        */
                        
                        System.out.println("columns" + "("+numElementsInRow+")  in Matrix" + "("+counter+")"  + " \t\trows("+rowsNextMatrix+")   in Matrix("+(counter+1)+")");
                    }
                    hasPerformedValidation=true;
                    
                    rowsNextMatrix=0;
            }

            numElementsInRow=0;

            //break;
            
            rowCounterFirstMatrix++;
        }
        
        rowCounterFirstMatrix=0;
        
        //at this point, we need to also wipe out contents of the intermediate matrix
        
        
        //}
        matrixNumber=counter;

        //since we alternate between matrixes
        counter=counter+2;

        hasStartMatrix=true;
        hasPerformedValidation=false;
        rowsNextMatrix=0;
        //hasProcessed=false;

        numMatrixes++;
        
        }while (counter<matricesSize);

        //System.out.println("num elements: " + numElementsInList);
        
        for (Integer []m: matrixMultiplication)
        {
            System.out.println(Arrays.toString(m));
        }
        
        //We need to present information in the same matrix dimensions, so
        //it will need another StringBuilder to ensure this is correct
        //We need StringBuilder for each row in matrixMultiplicationCalculations
        
        StringJoiner matrixRowCalculations;
        
        System.out.println("***CALCULATION STEPS*******");
        for (int q=0; q<matrixMultiplicationCalculations.length; q++)
            {
                matrixRowCalculations = new StringJoiner("");
                
                for (int r=0; r<matrixMultiplicationCalculations[0].length; r++)
                {
                    matrixRowCalculations.add(" ["+matrixMultiplicationCalculations[q][r]+"]");
                    
                }
                System.out.println(matrixRowCalculations);
            }
            
            System.out.println("\n"+excessRowReport);
        

        return finalMatrix;
    }
}